cmake_minimum_required(VERSION 3.28)
project(syralink)

message(STATUS "------ SyraLink build ------")

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
message(STATUS "build Generator: ${CMAKE_GENERATOR}")

# must support C++20
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++20" COMPILER_SUPPORTS_CXX20)
if(COMPILER_SUPPORTS_CXX20)
    set(CMAKE_CXX_STANDARD 20)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    set(CMAKE_CXX_EXTENSIONS  OFF)
else()
    message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++20 support")
endif()

# build type
if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE "Debug")
endif()
message(STATUS "build type: ${CMAKE_BUILD_TYPE}")

# --- compile options ---
set(LD_LIBS "")
add_compile_options(-Wall -Werror)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
    list(APPEND LD_LIBS asan ubsan lsan)
    add_compile_options(-g -O0)
    add_compile_options(-fsanitize=address -fsanitize=leak -fsanitize=undefined -lasan -lubsan)
else()
    add_compile_options(-O2)
endif()
list(APPEND LD_LIBS spdlog::spdlog ZLIB::ZLIB OpenSSL::Crypto)

find_package(ZLIB REQUIRED)
find_package(OpenSSL REQUIRED)
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")

# --- thirdparty ---
include(FetchContent)
set(THIRDPARTY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty)
# asio
message(STATUS "------ Fetch asio ------")
FetchContent_Declare(
    asio
    GIT_REPOSITORY https://gitee.com/mirrors_addons/asio.git
    GIT_TAG        asio-1-36-0
    GIT_SHALLOW    TRUE
    SOURCE_DIR     ${THIRDPARTY_DIR}/asio
)
FetchContent_MakeAvailable(asio)
add_compile_definitions(ASIO_STANDALONE)

# spdlog
message(STATUS "------ Fetch spdlog ------")
FetchContent_Declare(
    spdlog
    GIT_REPOSITORY https://gitee.com/mirrors_trending/spdlog.git
    GIT_TAG        v1.15.3
    GIT_SHALLOW    TRUE
    SOURCE_DIR     ${THIRDPARTY_DIR}/spdlog
)
FetchContent_MakeAvailable(spdlog)

# gtest
message(STATUS "------ Fetch GoogleTest ------")
FetchContent_Declare(
    googletest
    GIT_REPOSITORY https://gitee.com/mirrors/googletest.git
    GIT_TAG        v1.17.0
    GIT_SHALLOW    TRUE
    SOURCE_DIR     ${THIRDPARTY_DIR}/googletest
)
FetchContent_MakeAvailable(googletest)


# --- project target ---
set(commsrc src/syralink.cc src/loger.cc src/cipher.cc src/thrdpool.cc)

if(LINUX)
    list(APPEND commsrc
        src/linux_network.cc
        src/linux_excutor.cc
    )
endif()

include_directories(include)
include_directories(thirdparty/asio/asio/include)
include_directories(thirdparty/spdlog/include)

add_executable(syralink-listener src/syralink-listener.cc ${commsrc})
target_link_libraries(syralink-listener PRIVATE ${LD_LIBS})

add_executable(syralink-connector src/syralink-connector.cc ${commsrc})
target_link_libraries(syralink-connector PRIVATE ${LD_LIBS})

# test
enable_testing()

# Add test executable
add_executable(unit_tests 
    test/main.cc
    test/loger_test.cc
    test/cipher_test.cc
    test/network_test.cc
    test/thrdpool_test.cc
    test/excutor_test.cc

    ${commsrc}
)

target_include_directories(unit_tests 
    PRIVATE 
    ${CMAKE_CURRENT_SOURCE_DIR}/include
    ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/asio/asio/include
    ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/spdlog/include
    ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/googletest/googletest/include
)

target_link_libraries(unit_tests 
    PRIVATE ${LD_LIBS}
    GTest::gtest 
    GTest::gtest_main
)

# Add tests to CTest
add_test(NAME unit_tests COMMAND unit_tests)
